#include "qmodelsaver.h"

QModelSaver::QModelSaver(void){;}

bool QModelSaver::startElement(const QString&, const QString&, const QString &name, const QXmlAttributes &attrs)
{
    //    if (name == "CELL") {
    //        for (int i=0; i<attrs.count(); ++i) {
    //            if (attrs.localName(i) == "beta") cell.beta = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "dt") cell.dt = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "eMax") cell.eMax= attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "eMin") cell.eMin = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "fpol") cell.fpol = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "fadh") cell.fadh = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "fcon") cell.fcon = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "h") cell.h = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "mu") cell.mu = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "scale") cell.scale = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "sigmaAV") cell.sigmaAV = attrs.value(i).toDouble();
    //            else if (attrs.localName(i) == "sigma") cell.sigma = attrs.value(i).toDouble();
    //        }
    //    }

    if (name == "NODE")
    {
        NODE node;

        for (int i=0; i<attrs.count(); ++i)
        {
            if (attrs.localName(i) == "isBoundary") node.isBoundary = attrs.value(i).toInt();
            else if (attrs.localName(i) == "isFrontal") node.isFrontal = attrs.value(i).toInt();
            else if (attrs.localName(i) == "pos.x") node.pos = QPointF(attrs.value(i).toDouble(), node.pos.y());
            else if (attrs.localName(i) == "pos.y") node.pos = QPointF(node.pos.x(), attrs.value(i).toDouble());
        }

        cell.nodes << node;
    }

    if (name == "EDGE")
    {
        EDGE edge;

        for (int i=0; i<attrs.count(); ++i)
        {
            if (attrs.localName(i) == "area") edge.area = attrs.value(i).toDouble();
            else if (attrs.localName(i) == "defaultLength") edge.defaultLength = attrs.value(i).toDouble();
            else if (attrs.localName(i) == "id1") edge.id1 = attrs.value(i).toInt();
            else if (attrs.localName(i) == "id2") edge.id2 = attrs.value(i).toInt();
            else if (attrs.localName(i) == "id3") edge.id3 = attrs.value(i).toInt();
            else if (attrs.localName(i) == "id4") edge.id4 = attrs.value(i).toInt();
            else if (attrs.localName(i) == "isBoundary") edge.isBoundary = attrs.value(i).toInt();
        }

        cell.edges << edge;
    } if (name == "AREA")
    {
    AREA area;

    for (int i=0; i<attrs.count(); ++i)
    {
        if (attrs.localName(i) == "topLeft.x") area.rect = QRectF(attrs.value(i).toDouble(), area.rect.topLeft().y(),
                                                                  area.rect.width(), area.rect.height());
        if (attrs.localName(i) == "topLeft.y") area.rect = QRectF(area.rect.topLeft().x(), attrs.value(i).toDouble(),
                                                                  area.rect.width(), area.rect.height());\
        if (attrs.localName(i) == "width") area.rect = QRectF(area.rect.topLeft().x(), area.rect.topLeft().y(),
                                                              attrs.value(i).toDouble(), area.rect.height());
        if (attrs.localName(i) == "height") area.rect = QRectF(area.rect.topLeft().x(), area.rect.topLeft().y(),
                                                               area.rect.width(), attrs.value(i).toDouble());
        if (attrs.localName(i) == "sigma") area.sigma = attrs.value(i).toDouble();
    }

    cell.areas << area;
}

    return true;
}

CELL& QModelSaver::getCell(void)
{
    return cell;
}

void QModelSaver::saveXmlModel(const CELL& _cell, const QString& fileName)
{
    QFile *file = new QFile(fileName);
    file->open(QIODevice::WriteOnly);
    QTextStream out(file);

    cell = _cell;

    QDomDocument *xmlFile = new QDomDocument;
    QDomElement rootElement = xmlFile->createElement("CELL");
    xmlFile->appendChild(rootElement);

    rootElement.setAttribute("beta", cell.beta);
    rootElement.setAttribute("dt", cell.dt);
    rootElement.setAttribute("eMax", cell.eMax);
    rootElement.setAttribute("eMin", cell.eMin);
    rootElement.setAttribute("fpol", cell.fpol);
    rootElement.setAttribute("fadh", cell.fadh);
    rootElement.setAttribute("fcon", cell.fcon);
    rootElement.setAttribute("h", cell.h);
    rootElement.setAttribute("mu", cell.mu);
    rootElement.setAttribute("scale", cell.scale);
    rootElement.setAttribute("sigma", cell.sigma);
    rootElement.setAttribute("sigmaAV", cell.sigmaAV);

    for (int i=0; i<cell.nodes.length(); ++i)
    {
        QDomElement domElement = xmlFile->createElement("NODE");

        domElement.setAttribute("id", i);

        domElement.setAttribute("isBoundary", cell.nodes[i].isBoundary);
        domElement.setAttribute("isFrontal", cell.nodes[i].isFrontal);
        domElement.setAttribute("pos.x", cell.nodes[i].pos.x());
        domElement.setAttribute("pos.y", cell.nodes[i].pos.y());

        rootElement.appendChild(domElement);
    }

    for (int i=0; i<cell.edges.length(); ++i)
    {
        QDomElement domElement = xmlFile->createElement("EDGE");

        domElement.setAttribute("id", i);

        domElement.setAttribute("area", cell.edges[i].area);
        domElement.setAttribute("defaultLength", cell.edges[i].defaultLength);
        domElement.setAttribute("id1", cell.edges[i].id1);
        domElement.setAttribute("id2", cell.edges[i].id2);
        domElement.setAttribute("id3", cell.edges[i].id3);
        domElement.setAttribute("id4", cell.edges[i].id4);

        rootElement.appendChild(domElement);
    }

    for (int i=0; i<cell.areas.length(); ++i)
    {
        QDomElement domElement = xmlFile->createElement("AREA");

        domElement.setAttribute("id", i);

        domElement.setAttribute("topLeft.x", cell.areas[i].rect.topLeft().x());
        domElement.setAttribute("topLeft.y", cell.areas[i].rect.topLeft().y());
        domElement.setAttribute("width", cell.areas[i].rect.width());
        domElement.setAttribute("height", cell.areas[i].rect.height());
        domElement.setAttribute("sigma", cell.areas[i].sigma);

        rootElement.appendChild(domElement);
    }

    out.setCodec("UTF-8");
    xmlFile->save(out, 4, QDomNode::EncodingFromTextStream);
    file->close();
}

void QModelSaver::importPlainTextModel(const QString& fileName)
{
    QFile fileNodes(fileName);
    fileNodes.open(QFile::ReadOnly);

    QTextStream inNodes(&fileNodes);

    double x = 0;
    double y = 0;

    NODE node;

    while (!inNodes.atEnd())
    {
        inNodes >> x >> y;
        if ((x>0)&&(y>0))
        {
            node.pos = QPointF(x,y);
            node.adhesionPos = QPointF(x,y);
            cell.nodes.append(node);
        }
    }

    fileNodes.close();

    //If there is any <fileName>.edges file, load it
    QFile fileEdges(QString(fileName).replace(QString(".nodes"),QString(".edges")));

    if (fileEdges.exists())
    {
        fileEdges.open(QFile::ReadOnly);
        QTextStream inEdges(&fileEdges);

        double id1 = 0;
        double id2 = 0;
        double id3 = 0;

        EDGE edge;

        while (!inEdges.atEnd())
        {
            inEdges >> id1 >> id2 >> id3;
            if ((id1>0)&&(id2>0)&&(id3>0))
            {
                id1--;
                id2--;
                id3--;

                int id12 = -1;
                int id23 = -1;
                int id31 = -1;

                //looking for the existing edges
                //if edge exists, add third id to the edge.id4, i.e. add a last triangle on this edge
                //if not, add edge, add the third id to the edge.id3, i.e. add a first triangle on this edge

                for (int i=0; i<cell.edges.length(); ++i)
                {
                    if (((cell.edges[i].id1 == id1)&&(cell.edges[i].id2 == id2)) ||
                        ((cell.edges[i].id1 == id2)&&(cell.edges[i].id2 == id1))) id12 = i;
                    if (((cell.edges[i].id1 == id2)&&(cell.edges[i].id2 == id3)) ||
                        ((cell.edges[i].id1 == id3)&&(cell.edges[i].id2 == id2))) id23 = i;
                    if (((cell.edges[i].id1 == id3)&&(cell.edges[i].id2 == id1)) ||
                        ((cell.edges[i].id1 == id1)&&(cell.edges[i].id2 == id3))) id31 = i;
                }

                if (id12>=0)
                {
                    cell.edges[id12].id4 = id3;
                }
                else
                {
                    edge.id1 = id1;
                    edge.id2 = id2;
                    edge.id3 = id3;
                    cell.edges << edge;
                }

                if (id23>=0)
                {
                    cell.edges[id23].id4 = id1;
                }
                else
                {
                    edge.id1 = id2;
                    edge.id2 = id3;
                    edge.id3 = id1;
                    cell.edges << edge;
                }

                if (id31>=0)
                {
                    cell.edges[id31].id4 = id2;
                }
                else
                {
                    edge.id1 = id3;
                    edge.id2 = id1;
                    edge.id3 = id2;
                    cell.edges << edge;
                }
            }
        }
        fileEdges.close();
    }
}

void QModelSaver::exportPlainTextModel(const CELL& _cell, const QString& fileName)
{
    QFile file(fileName);
    file.open(QFile::WriteOnly | QFile::Truncate);

    QTextStream out(&file);
    out.setCodec("UTF-8");

    cell = _cell;

    for (int i=0; i<cell.nodes.length(); ++i)
    {
        out << cell.nodes[i].pos.x() << " " << cell.nodes[i].pos.y() << endl;
    }

    file.close();
}
